package com.vimeworks.vimemannager.web.servlet;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Connection;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.base.JRBaseParameter;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import net.sf.jasperreports.engine.util.JRLoader;

public class ReporteServlet extends HttpServlet {

	private static final long serialVersionUID = 2626123244565226183L;
	private static final Logger LOG = Logger.getLogger(ReporteServlet.class.getName());
	
	@Resource(mappedName="java:jdbc/VimeManager")
	private DataSource dataSource;

	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		generarReporte(req, resp);
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		generarReporte(req, resp);

	}

	private void generarReporte(HttpServletRequest request, HttpServletResponse response) {
		try {
			String tipoReporte = request.getParameter("tipo");
			JasperReport reporte = obtenerReporte(request);
			JasperPrint jasperPrint = null;
			jasperPrint = cargarReporteBDD(reporte, request, obtenerParametros(reporte, request), dataSource.getConnection());
			dataSource.getConnection().close(); 
			if (jasperPrint != null) {
				if (tipoReporte.equals("PDF")) {
					visualizarReportePdf(request, response, jasperPrint);
				} else if (tipoReporte.equals("EXCEL")) {
					visualizarReporteExcel(request, response, jasperPrint);
				}
			} else {
				imprimirMensajeError(request, "En la generacion del reporte retorna nulo", new Exception("En la generacion del reporte retorna nulo"));
			}
		} catch (Exception e) {
			imprimirMensajeError(request, "Error en el proceso de generacion del reporte", e);
		}
	}

	@SuppressWarnings("unused")
	private JasperPrint cargarReporteObjetos(JasperReport reporte, HttpServletRequest request, Map<String, Object> parametros, List<?> dataSource) {
		try {
			JRDataSource reportDataSource = new JRBeanCollectionDataSource(dataSource);
			JasperPrint jasperPrint = null;
			jasperPrint = JasperFillManager.fillReport(reporte, parametros, reportDataSource);
			return jasperPrint;
		} catch (Exception e) {
			imprimirMensajeError(request, "En la carga de los objetos al reporte", e);
			return null;
		}
	}

	private JasperPrint cargarReporteBDD(JasperReport reporte, HttpServletRequest request, Map<String, Object> parametros, Connection connection) {
		try {
			JasperPrint jasperPrint = null;
			jasperPrint = JasperFillManager.fillReport(reporte, parametros, connection);
			return jasperPrint;
		} catch (Exception e) {
			imprimirMensajeError(request, "En la carga del datasource y los datos al reporte", e);
			return null;
		}
	}

	private void visualizarReportePdf(HttpServletRequest request, HttpServletResponse response, JasperPrint jasperPrint) {
		try {
			response.setContentType("application/pdf");
			ServletOutputStream out = response.getOutputStream();
			JasperExportManager.exportReportToPdfStream(jasperPrint, out);
		} catch (Exception e) {
			imprimirMensajeError(request, "Error en la exportacion del reporte a PDF", e);
		}
	}

	private void visualizarReporteExcel(HttpServletRequest request, HttpServletResponse response, JasperPrint jasperPrint) {
		try {
			response.setContentType("application/vnd.ms-excel");
			ServletOutputStream out = response.getOutputStream();
			JRXlsExporter exporterXLS = new JRXlsExporter();
			exporterXLS.setParameter(JRXlsExporterParameter.JASPER_PRINT, jasperPrint);
			exporterXLS.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, out);
			exporterXLS.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
			exporterXLS.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
			exporterXLS.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
			exporterXLS.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
			exporterXLS.exportReport();
		} catch (Exception e) {
			imprimirMensajeError(request, "Error en la exportacion del reporte a EXCEL", e);
		}
	}

	private Map<String, Object> obtenerParametros(JasperReport reporte, HttpServletRequest request) throws ParseException, MalformedURLException, JRException {
		Map<String, Object> parametros = new HashMap<String, Object>();
		JRParameter parameter[] = reporte.getParameters();
		for (int i = 0; i < parameter.length; i++) {
			JRBaseParameter param = (JRBaseParameter) parameter[i];
			if (!param.isSystemDefined()) {
				if (param.isForPrompting()) {
					String arg = param.getName();
					Object obj = null;
					if (param.getValueClassName().equals("net.sf.jasperreports.engine.JasperReport")) {

					} else {
						String value = request.getParameter(arg);
						if (value != null) {
							if (param.getValueClassName().equals("java.lang.String")) {
								obj = value;
							} else if (param.getValueClassName().equals("java.lang.Long")) {
								Long longValue = new Long(value);
								obj = longValue;
							} else if (param.getValueClassName().equals("java.util.Date")) {
								SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
								Date value_date = sdf.parse(value);
								obj = value_date;
							} else if (param.getValueClassName().equals("java.lang.Boolean")) {
								Boolean boolValue = new Boolean(value);
								obj = boolValue;
							} else if (param.getValueClassName().equals("java.lang.Integer")) {
								Integer integerValue = new Integer(value);
								obj = integerValue;
							} else if (param.getValueClassName().equals("java.lang.Double")) {
								Double doubleValue = new Double(value);
								obj = doubleValue;
							} else if (param.getValueClassName().equals("java.lang.Float")) {
								Float floatValue = new Float(value);
								obj = floatValue;
							} else if (param.getValueClassName().equals("java.sql.Timestamp")) {
								SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
								Timestamp timestampValue = new Timestamp(sdf.parse(value).getTime());
								obj = timestampValue;
							} else if (param.getValueClassName().equals("java.math.BigDecimal")) {
								BigDecimal bigDecimalValue = new BigDecimal(value);
								obj = bigDecimalValue;
							} else if (param.getValueClassName().equals("java.lang.Short")) {
								Short shortValue = new Short(value);
								obj = shortValue;
							} else if (param.getValueClassName().equals("java.lang.Object")) {
								obj = value;
							}
						}
					}
					parametros.put(arg, obj);
				}
			}
		}
		parametros.put("SUBREPORT_DIR", obtenerPathReporte(request));
		parametros.put("URL_IMAGEN", obtenerPathImagen(request));
		return parametros;
	}

	private JasperReport obtenerReporte(HttpServletRequest request) throws MalformedURLException, JRException {
		String pathAplicacion = "";
		if (request.isSecure()) {
			pathAplicacion += "https://";
		} else {
			pathAplicacion += "http://";
		}
		String nombre = request.getParameter("nombre");
		pathAplicacion += request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
		String pathReporte = pathAplicacion + "/paginas/reportes/jasper/";
		pathReporte = (pathReporte + nombre + ".jasper");
		URL url = new URL(pathReporte);
		JasperReport reporte = (JasperReport) JRLoader.loadObject(url);
		return reporte;
	}

	private String obtenerPathReporte(HttpServletRequest request) throws MalformedURLException, JRException {
		String pathAplicacion = "";
		if (request.isSecure()) {
			pathAplicacion += "https://";
		} else {
			pathAplicacion += "http://";
		}
		pathAplicacion += request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
		String pathReporte = pathAplicacion + "/paginas/reportes/jasper/";
		return pathReporte;
	}

	private String obtenerPathImagen(HttpServletRequest request) throws MalformedURLException, JRException {
		String pathAplicacion = "";
		if (request.isSecure()) {
			pathAplicacion += "https://";
		} else {
			pathAplicacion += "http://";
		}
		pathAplicacion += request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
		String pathImagen = pathAplicacion + "/images/logo.gif";
		return pathImagen;
	}

	public void imprimirMensajeError(HttpServletRequest request, String mensaje, Exception ex) {
		ex.printStackTrace();
		String reporte = request.getParameter("nombre");

		try {

			StringBuffer sb = new StringBuffer();
			sb.append("\n");
			sb.append("----------------------------------------------------------------------------\n");
			sb.append("                     ERROR EN A GENERACION DEL REPORTE\n");
			sb.append("----------------------------------------------------------------------------\n");
			sb.append(" Mensaje: " + mensaje + "\n");
			sb.append(" Reporte: " + reporte + "\n");
			if (ex != null) {
				sb.append(" Error:   " + ex.getMessage() + "\n");
				StackTraceElement[] elementosError = ex.getStackTrace();
				if (elementosError != null && elementosError.length > 0) {
					sb.append(" Detalle:\n");
					for (int i = 0; i < elementosError.length; i++) {
						if (elementosError[i].getClassName().contains("ec.gob.supertel")) {
							sb.append("\n      Clase:  " + elementosError[i].getClassName() + "\n");
							sb.append("      Metodo: " + elementosError[i].getMethodName() + "\n");
							sb.append("      Linea:  " + elementosError[i].getLineNumber() + "\n");
						}
					}
				}
			}
			sb.append("----------------------------------------------------------------------------\n");
			LOG.severe(sb.toString());
		} catch (Exception e) {
			LOG.log(Level.SEVERE, " Error en la generación del reporte: " + reporte, e);
		}

	}

}
